/*
 * Copyright (c) 2023-2023 elsfs Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.elsfs.cloud.common.security.config;

import java.util.Locale;
import org.elsfs.cloud.api.security.service.SecurityUserService;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;

/**
 * 配置过滤器
 *
 * @param <C> 自身类型
 * @param <F> 过滤器
 * @author zeng
 */
public class AbstractSecurityFilterConfigurer<
        C extends AbstractSecurityFilterConfigurer<C, F>,
        F extends AbstractAuthenticationProcessingFilter>
    extends AbstractSecurityConfigurer<C> {
  protected final F filter;

  protected AbstractSecurityFilterConfigurer(F filter) {
    this.filter = filter;
  }

  protected PasswordEncoder getPasswordEncoder(HttpSecurity http) {
    PasswordEncoder passwordEncoder = http.getSharedObject(PasswordEncoder.class);
    try {
      if (passwordEncoder == null) {
        ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);
        passwordEncoder = applicationContext.getBean(PasswordEncoder.class);
      }
    } catch (BeansException e) {
      passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
    return passwordEncoder;
  }

  protected SecurityUserService getElsfsUserDetailsService(HttpSecurity http) {
    SecurityUserService elsfsUserDetailsService = http.getSharedObject(SecurityUserService.class);
    if (elsfsUserDetailsService == null) {
      ApplicationContext applicationContext = http.getSharedObject(ApplicationContext.class);
      elsfsUserDetailsService = applicationContext.getBean(SecurityUserService.class);
    }
    return elsfsUserDetailsService;
  }

  protected final MessageSource getMessageSource() {
    ReloadableResourceBundleMessageSource messageSource =
        new ReloadableResourceBundleMessageSource();
    messageSource.addBasenames("org.springframework.security.messages");
    messageSource.addBasenames("classpath:messages");
    messageSource.setDefaultLocale(Locale.CHINA);
    return messageSource;
  }

  @Override
  public void configure(HttpSecurity http) throws Exception {
    filter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
    filter.setAuthenticationSuccessHandler(super.successHandler);
    filter.setAuthenticationFailureHandler(super.failureHandler);
    http.addFilterBefore(filter, OAuth2LoginAuthenticationFilter.class);
  }
}
